package com.macrosoft.frpd.utils;

import android.content.Context;
import android.util.Log;
import android.widget.Toast;

import com.macrosoft.frpd.application.IConstants;

public class Logger implements IConstants {
	// ===========================================================
	// Constants
	// ===========================================================

	// ===========================================================
	// Fields
	// ===========================================================

	private static String sTag = DEBUGTAG;
	private static String sDebugUser = "";
	private static DebugLevel sDebugLevel = DebugLevel.VERBOSE;

	// ===========================================================
	// Constructors
	// ===========================================================

	// ===========================================================
	// Getter & Setter
	// ===========================================================

	public static String getTag() {
		return Logger.sTag;
	}

	public static void setTag(final String pTag) {
		Logger.sTag = pTag;
	}

	public static DebugLevel getDebugLevel() {
		return Logger.sDebugLevel;
	}

	public static void setDebugLevel(final DebugLevel pDebugLevel) {
		if (pDebugLevel == null) {
			throw new IllegalArgumentException("pDebugLevel must not be null!");
		}
		Logger.sDebugLevel = pDebugLevel;
	}

	public static void setDebugUser(final String pDebugUser) {
		if (pDebugUser == null) {
			throw new IllegalArgumentException("pDebugUser must not be null!");
		}
		Logger.sDebugUser = pDebugUser;
	}

	// ===========================================================
	// Methods for/from SuperClass/Interfaces
	// ===========================================================

	// ===========================================================
	// Methods
	// ===========================================================

	public static void log(final DebugLevel pDebugLevel, final String pMessage) {
		switch (pDebugLevel) {
		case NONE:
			return;
		case VERBOSE:
			Logger.v(pMessage);
			return;
		case INFO:
			Logger.i(pMessage);
			return;
		case DEBUG:
			Logger.d(pMessage);
			return;
		case WARNING:
			Logger.w(pMessage);
			return;
		case ERROR:
			Logger.e(pMessage);
			return;
		}
	}

	public static void log(final String pMessage, final Throwable pThrowable) {
		Logger.log(DebugLevel.ERROR, pMessage, pThrowable);
	}

	public static void log(final DebugLevel pDebugLevel, final String pMessage, final Throwable pThrowable) {
		switch (pDebugLevel) {
		case NONE:
			return;
		case VERBOSE:
			Logger.v(pMessage, pThrowable);
			return;
		case INFO:
			Logger.i(pMessage, pThrowable);
			return;
		case DEBUG:
			Logger.d(pMessage, pThrowable);
			return;
		case WARNING:
			Logger.w(pMessage, pThrowable);
			return;
		case ERROR:
			Logger.e(pMessage, pThrowable);
			return;
		}
	}

	public static void log(final DebugLevel pDebugLevel, final String pTag, final String pMessage) {
		switch (pDebugLevel) {
		case NONE:
			return;
		case VERBOSE:
			Logger.v(pTag, pMessage);
			return;
		case INFO:
			Logger.i(pTag, pMessage);
			return;
		case DEBUG:
			Logger.d(pTag, pMessage);
			return;
		case WARNING:
			Logger.w(pTag, pMessage);
			return;
		case ERROR:
			Logger.e(pTag, pMessage);
			return;
		}
	}

	public static void log(final DebugLevel pDebugLevel, final String pTag, final String pMessage, final Throwable pThrowable) {
		switch (pDebugLevel) {
		case NONE:
			return;
		case VERBOSE:
			Logger.v(pTag, pMessage, pThrowable);
			return;
		case INFO:
			Logger.i(pTag, pMessage, pThrowable);
			return;
		case DEBUG:
			Logger.d(pTag, pMessage, pThrowable);
			return;
		case WARNING:
			Logger.w(pTag, pMessage, pThrowable);
			return;
		case ERROR:
			Logger.e(pTag, pMessage, pThrowable);
			return;
		}
	}

	public static void v(final String pMessage) {
		Logger.v(Logger.sTag, pMessage, null);
	}

	public static void v(final String pMessage, final Throwable pThrowable) {
		Logger.v(Logger.sTag, pMessage, pThrowable);
	}

	public static void v(final String pTag, final String pMessage) {
		Logger.v(pTag, pMessage, null);
	}

	public static void v(final String pTag, final String pMessage, final Throwable pThrowable) {
		if (Logger.sDebugLevel.isSameOrLessThan(DebugLevel.VERBOSE)) {
			if (pThrowable == null) {
				Log.v(pTag, pMessage);
			} else {
				Log.v(pTag, pMessage, pThrowable);
			}
		}
	}

	public static void vUser(final String pMessage, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.v(pMessage);
		}
	}

	public static void vUser(final String pMessage, final Throwable pThrowable, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.v(pMessage, pThrowable);
		}
	}

	public static void vUser(final String pTag, final String pMessage, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.v(pTag, pMessage);
		}
	}

	public static void vUser(final String pTag, final String pMessage, final Throwable pThrowable, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.v(pTag, pMessage, pThrowable);
		}
	}

	public static void d(final String pMessage) {
		Logger.d(Logger.sTag, pMessage, null);
	}

	public static void d(final String pMessage, final Throwable pThrowable) {
		Logger.d(Logger.sTag, pMessage, pThrowable);
	}

	public static void d(final String pTag, final String pMessage) {
		Logger.d(pTag, pMessage, null);
	}

	public static void d(final String pTag, final String pMessage, final Throwable pThrowable) {
		if (Logger.sDebugLevel.isSameOrLessThan(DebugLevel.DEBUG)) {
			if (pThrowable == null) {
				Log.d(pTag, pMessage);
			} else {
				Log.d(pTag, pMessage, pThrowable);
			}
		}
	}

	public static void dUser(final String pMessage, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.d(pMessage);
		}
	}

	public static void dUser(final String pMessage, final Throwable pThrowable, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.d(pMessage, pThrowable);
		}
	}

	public static void dUser(final String pTag, final String pMessage, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.d(pTag, pMessage);
		}
	}

	public static void dUser(final String pTag, final String pMessage, final Throwable pThrowable, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.d(pTag, pMessage, pThrowable);
		}
	}

	public static void i(final String pMessage) {
		Logger.i(Logger.sTag, pMessage, null);
	}

	public static void i(final String pMessage, final Throwable pThrowable) {
		Logger.i(Logger.sTag, pMessage, pThrowable);
	}

	public static void i(final String pTag, final String pMessage) {
		Logger.i(pTag, pMessage, null);
	}

	public static void i(final String pTag, final String pMessage, final Throwable pThrowable) {
		if (Logger.sDebugLevel.isSameOrLessThan(DebugLevel.INFO)) {
			if (pThrowable == null) {
				Log.i(pTag, pMessage);
			} else {
				Log.i(pTag, pMessage, pThrowable);
			}
		}
	}

	public static void iUser(final String pMessage, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.i(pMessage);
		}
	}

	public static void iUser(final String pMessage, final Throwable pThrowable, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.i(pMessage, pThrowable);
		}
	}

	public static void iUser(final String pTag, final String pMessage, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.i(pTag, pMessage);
		}
	}

	public static void iUser(final String pTag, final String pMessage, final Throwable pThrowable, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.i(pTag, pMessage, pThrowable);
		}
	}

	public static void w(final String pMessage) {
		Logger.w(Logger.sTag, pMessage, null);
	}

	public static void w(final Throwable pThrowable) {
		Logger.w("", pThrowable);
	}

	public static void w(final String pMessage, final Throwable pThrowable) {
		Logger.w(Logger.sTag, pMessage, pThrowable);
	}

	public static void w(final String pTag, final String pMessage) {
		Logger.w(pTag, pMessage, null);
	}

	public static void w(final String pTag, final String pMessage, final Throwable pThrowable) {
		if (Logger.sDebugLevel.isSameOrLessThan(DebugLevel.WARNING)) {
			if (pThrowable == null) {
				Log.w(pTag, pMessage);
			} else {
				Log.w(pTag, pMessage, pThrowable);
			}
		}
	}

	public static void wUser(final String pMessage, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.w(pMessage);
		}
	}

	public static void wUser(final Throwable pThrowable, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.w(pThrowable);
		}
	}

	public static void wUser(final String pMessage, final Throwable pThrowable, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.w(pMessage, pThrowable);
		}
	}

	public static void wUser(final String pTag, final String pMessage, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.w(pTag, pMessage);
		}
	}

	public static void wUser(final String pTag, final String pMessage, final Throwable pThrowable, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.w(pTag, pMessage, pThrowable);
		}
	}

	public static void e(final String pMessage) {
		Logger.e(Logger.sTag, pMessage, null);
	}

	public static void e(final Throwable pThrowable) {
		Logger.e(Logger.sTag, pThrowable);
	}

	public static void e(final String pMessage, final Throwable pThrowable) {
		Logger.e(Logger.sTag, pMessage, pThrowable);
	}

	public static void e(final String pTag, final String pMessage) {
		Logger.e(pTag, pMessage, null);
	}

	public static void e(final String pTag, final String pMessage, final Throwable pThrowable) {
		if (Logger.sDebugLevel.isSameOrLessThan(DebugLevel.ERROR)) {
			if (pThrowable == null) {
				Log.e(pTag, pMessage);
			} else {
				Log.e(pTag, pMessage, pThrowable);
			}
		}
	}

	public static void eUser(final String pMessage, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.e(pMessage);
		}
	}

	public static void eUser(final Throwable pThrowable, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.e(pThrowable);
		}
	}

	public static void eUser(final String pMessage, final Throwable pThrowable, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.e(pMessage, pThrowable);
		}
	}

	public static void eUser(final String pTag, final String pMessage, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.e(pTag, pMessage);
		}
	}

	public static void eUser(final String pTag, final String pMessage, final Throwable pThrowable, final String pDebugUser) {
		if (Logger.sDebugUser.equals(pDebugUser)) {
			Logger.e(pTag, pMessage, pThrowable);
		}
	}

	/**
	 * Call from <b>UI Thread</b>
	 */
	public static void showToast(final Context pContext, final String pMessage, final int pDuration) {
		Toast.makeText(pContext, pMessage, pDuration).show();
	}

	// ===========================================================
	// Inner and Anonymous Classes
	// ===========================================================

	public static enum DebugLevel implements Comparable<DebugLevel> {
		NONE, ERROR, WARNING, INFO, DEBUG, VERBOSE;

		public static DebugLevel ALL = DebugLevel.VERBOSE;

		public boolean isSameOrLessThan(final DebugLevel pDebugLevel) {
			return this.compareTo(pDebugLevel) >= 0;
		}
	}
}
